import React, { useCallback, useRef, useState, useMemo, useEffect } from 'react';
import {
    ReactFlow,
    MiniMap,
    Controls,
    Background,
    useNodesState,
    useEdgesState,
    addEdge,
    Panel,
    BackgroundVariant,
    MarkerType,
    ReactFlowProvider,
    useOnSelectionChange,
    useReactFlow,
    useStoreApi,
} from '@xyflow/react';
import './App.css'

import '@xyflow/react/dist/style.css';
import { AggregateNode, JoinNode, NodeTypes, PreprocessNode, SinkNode, SqlNode, UnionNode } from '@/components/DataFlow/CustomNode';
import PropertyPanel from '@/components/DataFlow/PropertyPanel';
import ContextMenu from '@/components/DataFlow/ContextMenu';
import useContextMenuStore from '@/store/ContextMenu';
import useDesignerStore from '@/store/Designer';
import { ConfigProvider, Dropdown, Modal, ThemeConfig } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import { EdgeTypes } from './components/DataFlow/CustomEdge';
import NarrowNodePanel from './components/DataFlow/NarrowNodePanel';
import FlowControl from './components/DataFlow/FlowControl';
import { cloneDeep, debounce, isEqual, throttle } from 'lodash-es';
import { useModelStore } from './store/MetaModel';
import StarterForm from './components/DataFlow/PropertyForm/CanvasForm';
import { Starter } from './components/DataFlow/PropertyForm/Starter';
import { NodeColor } from './constant';
import { graph } from './assets/graph';
import { CloseOutlined } from '@ant-design/icons';
import { randomUUID } from './utils/dataflow';

const ReactFlowApp = () => {
    const [nodes, setNodes, onNodesChange] = useNodesState(graph.nodes ?? []);
    const [edges, setEdges, onEdgesChange] = useEdgesState(graph.edges ?? []);
    const flowInsatnce = useRef(null)
    const flowElemRef = useRef(null)
    const { dragNode, background, miniMap, setSelectedNodes, setSelectedEdges } = useDesignerStore()
    const showContext = useContextMenuStore(state => state.showContext)
    const closeContext = useContextMenuStore(state => state.closeContext)
    const { addNodes } = useReactFlow()
    const modalRef = useRef(null)
    const store = useStoreApi()
    const { updateNodeData, getNode } = useReactFlow()

    // the passed handler has to be memoized, otherwise the hook will not work correctly
    const onChange = useCallback(({ nodes, edges }) => {
        setSelectedNodes(nodes);
        setSelectedEdges(edges);
    }, []);

    useOnSelectionChange({
        onChange,
    });

    function findDirectPredecessors(nodeId) {
        return edges
            ?.filter(edge => edge.target === nodeId) // 找到所有指向该节点的边
            ?.map(edge => edge.source);             // 提取源节点ID
    }


    const onConnect = useCallback((connection) => {
        // 添加边
        setEdges((eds) => addEdge(connection, eds))

        const { nodeLookup } = store.getState();
        // 获取源节点和目标节点
        const sourceNode = nodeLookup.get(connection.source);
        const targetNode = nodeLookup.get(connection.target);

        if (targetNode?.type === PreprocessNode.displayName) {
            console.debug('目标节点为预处理', targetNode)
            // 获取数据源
            const sourceColumns = sourceNode.data?.columns ?? [];
            const oldTargetColumns = targetNode.data?.allColumns ?? [];

            // 合并策略：保留上游所有列 + 目标节点生成的自定义列
            const preservedCustomColumns = oldTargetColumns?.filter(col =>
                col.isGenerated &&  // 标记为生成的列
                !sourceColumns?.some(sCol => sCol.columnId === col.columnId) // 不与上游列冲突
            );

            // 合并顺序：自定义列在前，上游列在后（可根据需求调整顺序）
            const newColumns = [
                ...sourceColumns,
                ...preservedCustomColumns,
            ];
            debugger

            // 深度比较避免无效更新
            if (!isEqual(oldTargetColumns, newColumns)) {
                // 使用异步更新确保状态一致性
                requestAnimationFrame(() => {
                    updateNodeData(targetNode.id, {
                        allColumns: newColumns,
                    });
                });
            }

        } else if (targetNode?.type === JoinNode.displayName) {
            console.debug('目标节点为关联', targetNode)
        }

    }, [])

    const onEdgesDelete = (connctions) => {
        console.error('边删除', connctions)
    }

    const handleClose = () => {
        modalRef.current?.destroy?.()
        modalRef.current = null
    }
    useEffect(() => {
        if (false) {
            modalRef.current = Modal.confirm({
                content: <Starter onClose={handleClose} />,
                maskClosable: false,
                footer: null,
                title: null,
                icon: null,
                className: 'starter-modal',
                width: 940,
                wrapClassName: 'starter-modal-wrapper',
                styles: {
                    body: {
                        width: '100%',
                        borderRadius: 10
                    },
                    content: {
                        padding: 0,
                    },
                }
            })
        }
    }, [])

    const onDrop = useCallback(
        (event) => {
            event.preventDefault();
            if (!dragNode) {
                return;
            }
            const viewPort = flowInsatnce.current?.getViewport?.() ?? { x: 0, y: 0, zoom: 1 }

            const position = {
                x: (event.clientX - viewPort.x) / viewPort.zoom - 110,
                y: (event.clientY - viewPort.y) / viewPort.zoom - 55,
            };
            const newNode = {
                id: randomUUID(),
                type: dragNode?.type,
                position,
                data: { ...dragNode },
            };

            addNodes(newNode)
        },
        [dragNode],
    );
    const onDragOver = useCallback((event) => {
        event.preventDefault();
        event.dataTransfer.dropEffect = 'move';
    }, []);

    const onContextMenu = useCallback((event, data) => {
        event.preventDefault();
        const pane = flowElemRef.current?.getBoundingClientRect();
        showContext(
            {
                id: data?.id,
                type: data?.type,
            },
            {
                top: event.clientY,
                left: event.clientX < pane.width - 200 && event.clientX || event?.clientX - 150,
            });
    }, [])

    const onInit = (e) => {
        flowInsatnce.current = e
    }

    const isValidConnection = useCallback(({ source, target }) => {
        const sourceNode = getNode(source)
        const targetNode = getNode(target)

        if (targetNode?.type === SqlNode.displayName) { //输入
            return false
        }
        if (sourceNode?.type === SinkNode.displayName) { //输出
            return false
        }
        const currentEdges = edges?.filter(e => e.target === targetNode?.id)
        if ([PreprocessNode.displayName, AggregateNode.displayName,
        SinkNode.displayName].includes(targetNode?.type)) { //判断已连接边的数量
            if (currentEdges?.length >= 1) {
                return false
            }
        } else if ([JoinNode.displayName].includes(targetNode?.type)) { //判断已连接边的数量
            if (currentEdges?.length >= 2) {
                return false
            }
        }
        return true
    }, [])


    return (
        <ReactFlow
            ref={flowElemRef}
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onEdgesDelete={onEdgesDelete}
            onDrop={onDrop}
            onDragOver={onDragOver}
            nodeTypes={NodeTypes}
            edgeTypes={EdgeTypes}
            proOptions={{ hideAttribution: true }}
            onNodeContextMenu={(evt, node) => onContextMenu(evt, { id: node.id, type: 'node' })}
            onPaneContextMenu={(evt) => onContextMenu(evt, { type: 'canvas', id: null })}
            onEdgeContextMenu={(evt, edge) => onContextMenu(evt, { id: edge.id, type: 'edge' })}
            onPaneClick={closeContext}
            onInit={onInit}
            selectionOnDrag={false}
            selectNodesOnDrag={false}
            isValidConnection={isValidConnection}
            defaultEdgeOptions={{
                type: 'RemovableEdge',
                markerEnd: {
                    type: MarkerType.ArrowClosed,
                    width: 30,
                    height: 30
                }
            }}
        >
            {miniMap !== 'hidden' && <MiniMap position={miniMap} nodeColor={NodeColor} pannable zoomable />}
            {background !== 'hidden' && <Background variant={background} lineWidth={1} />}
            <ContextMenu />
            <PropertyPanel />
            <Panel position='top-right'>
                <FlowControl />
            </Panel>
            <Panel position='top-left' style={{ top: '15%' }}>
                <NarrowNodePanel />
            </Panel>
        </ReactFlow>
    );
}
// const theme: ThemeConfig = {
//   token: {
//     colorPrimary: '#009983',
//     // boxShadow: '0 3px 3px 3px #00998355'
//   }
// }
const App = () => (
    <ConfigProvider locale={zhCN}>
        <ReactFlowProvider>
            <ReactFlowApp />
        </ReactFlowProvider>
    </ConfigProvider>
)
export default App